package com.luyu.tenant;

import com.luyu.entity.User;
import com.luyu.temp.TempUserInfo;
import com.luyu.temp.TempUserInfoUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class TenantUserInfoAspect {


    @Resource
    private UserDetailsService userDetailsService;


    @Resource
    private TempUserInfoUtil userInfoUtil;

    @Pointcut(value = "execution(* com.luyu..controller..*.*(..))")
    public void methodTenantId() {
        System.out.printf("methodTenantId");
    }


    @Around("methodTenantId()")
    public Object extractTenantId2(ProceedingJoinPoint joinPoint) {
        // 获取tenantId
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        String[] parameterNames = methodSignature.getParameterNames();
        int tenantParamIndex = -1;
        for (int i = 0; i < parameterNames.length; i++) {
            if ("tenantId".equals(parameterNames[i])) {
                tenantParamIndex = i;
            }
        }
        // 访问已登录接口，转换信息
        if (tenantParamIndex >= 0) {
            String tenantId = joinPoint.getArgs()[tenantParamIndex].toString();
            TenantContextHolder.setTenantId(Long.valueOf(tenantId));
            // 将jwt转换成用户上下文
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            User userDetails = (User) authentication.getPrincipal();
            String userName = authentication.getName();
            // 获取用户当前角色id
            TempUserInfo tempUserInfo = userInfoUtil.getTempUserInfo(userName, Long.valueOf(tenantId));
            if (tempUserInfo == null) {
                throw new RuntimeException("用户未登录");
            }
            Long currentRoleId = tempUserInfo.getCurrentRoleId();

            if (authentication instanceof Jwt jwt) {
                userName = jwt.getClaimAsString(JwtClaimNames.SUB);
                userDetails = (User) userDetailsService.loadUserByUsername(userName);
            }
            userDetails.setCurrentRoleId(currentRoleId);
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            userDetails.eraseCredentials();
            SecurityContextHolder.clearContext();
            SecurityContextHolder.getContext().setAuthentication(token);
            log.info("替换上下文");
        }
        // 方法执行并放行
        Object proceed;
        try {
            proceed = joinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            TenantContextHolder.remove();
        }
        return proceed;
    }


}
